package org.kermeta.spem.activityautomation.eclipse.creatextextproject.actions;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.codegen.ecore.genmodel.GenModel;
import org.eclipse.emf.codegen.ecore.genmodel.GenPackage;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.xtext.ui.wizard.IProjectInfo;
import org.eclipse.xtext.xtext.ui.wizard.ecore2xtext.EPackageInfo;
import org.eclipse.xtext.xtext.ui.wizard.ecore2xtext.Ecore2XtextProjectCreator;
import org.eclipse.xtext.xtext.ui.wizard.ecore2xtext.Ecore2XtextProjectInfo;
import org.eclipse.xtext.xtext.ui.wizard.ecore2xtext.Messages;
import org.eclipse.xtext.xtext.ui.wizard.project.NewXtextProjectWizard;
import org.eclipse.xtext.xtext.ui.wizard.project.XtextProjectInfo;

import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.inject.Inject;
import com.google.inject.name.Named;

public class NewXtextProjectFromEcoreWizard2 extends NewXtextProjectWizard {
	
	@Inject
	@Named("genModelUri")
	private String genModelURI;

	/**
	 * Constructs a new wizard
	 */
	@SuppressWarnings("restriction")
	@Inject
	public NewXtextProjectFromEcoreWizard2(Ecore2XtextProjectCreator creator) {
		super(creator);
		setWindowTitle(Messages.NewXtextProjectFromEcoreWizard_WindowTitle);
	}

	@Override
	protected IProjectInfo getProjectInfo() {
		Ecore2XtextProjectInfo projectInfo = (Ecore2XtextProjectInfo) super.getProjectInfo();
		projectInfo.setEPackageInfos(createEPackageInfosFromGenModel(URI.createURI(genModelURI)));
		projectInfo.setRootElementClass(getRootElementClass());
		projectInfo.setDefaultEPackageInfo(createEPackageInfosFromGenModel(URI.createURI(genModelURI)).get(0));
		return projectInfo;
	}

	@Override
	protected XtextProjectInfo createProjectInfo() {
		return new Ecore2XtextProjectInfo();
	}
	
	protected List<EPackageInfo> createEPackageInfosFromGenModel(URI genModelURI) {
		ResourceSet resourceSet = createResourceSet();
		Resource resource = resourceSet.getResource(genModelURI, true);
		List<EPackageInfo> ePackageInfos = Lists.newArrayList();
		for (TreeIterator<EObject> i = resource.getAllContents(); i.hasNext();) {
			EObject next = i.next();
			if (next instanceof GenPackage) {
				GenPackage genPackage = (GenPackage) next;
				EPackage ePackage = genPackage.getEcorePackage();
				URI importURI;
				if(ePackage.eResource() == null) {
					importURI = URI.createURI(ePackage.getNsURI());
				} else {
					importURI = ePackage.eResource().getURI();
				}
				EPackageInfo ePackageInfo = new EPackageInfo(ePackage, importURI, genModelURI, genPackage
						.getQualifiedPackageInterfaceName(), genPackage.getGenModel().getModelPluginID());
				ePackageInfos.add(ePackageInfo);
			} else if (!(next instanceof GenModel)) {
				i.prune();
			}
		}
		return ePackageInfos;
	}
	
	private ResourceSet createResourceSet() {
		ResourceSetImpl resourceSet = new ResourceSetImpl();
		Resource ecorePackageResource = EcorePackage.eINSTANCE.eResource();
		Map<URI, Resource> uriResourceMap = Maps.newHashMap();
		uriResourceMap.put(URI.createPlatformResourceURI("org.eclipse.emf.ecore/model/Ecore.ecore", true), ecorePackageResource);
		uriResourceMap.put(URI.createPlatformPluginURI("org.eclipse.emf.ecore/model/Ecore.ecore", true), ecorePackageResource);
		resourceSet.setURIResourceMap(uriResourceMap);
		return resourceSet;
	}
	
	public EClass getRootElementClass() {
		Iterable<EClass> eClasses = Iterables.filter(Iterables.concat(Iterables.transform(createEPackageInfosFromGenModel(URI.createURI(genModelURI)),
				new Function<EPackageInfo, List<EClassifier>>() {
					public List<EClassifier> apply(EPackageInfo from) {
						return from.getEPackage().getEClassifiers();
					}
				})), EClass.class);
		List<EClass> result = Lists.newArrayList(eClasses);
		Collections.sort(result, new Comparator<EClass>() {
			public int compare(EClass o1, EClass o2) {
				return o1.getName().compareTo(o2.getName());
			}
		});
		Object[] obj = Iterables.toArray(result, EClass.class);
		return (EClass) obj[0];
	}

}

